package de.jmda.gen.impl;

import javax.validation.constraints.NotNull;

import de.jmda.gen.Generator;
import de.jmda.gen.GeneratorException;
import de.jmda.gen.LineIndenter;

public class DefaultGenerator implements Generator
{
	private StringBuffer output;

	/**
	 * Non null, but maybe producing nothing but "empty" string <code>""</code>.
	 */
	@NotNull(message = "'lineIndenter' must not be null")
	private LineIndenter lineIndenter;

	protected DefaultGenerator()
	{
		this(new StringBuffer(""), new LineIndenter());
	}

	public DefaultGenerator(String input)
	{
		this(new StringBuffer(input), new LineIndenter());
	}

	public DefaultGenerator(StringBuffer input)
	{
		this(input, new LineIndenter());
	}

	public DefaultGenerator(String input, LineIndenter lineIndenter)
	{
		this(new StringBuffer(input), lineIndenter);
	}

	public DefaultGenerator(StringBuffer input, LineIndenter lineIndenter)
	{
		super();

		setOutput(input);
		setLineIndenter(lineIndenter);
	}

	/**
	 * @param lineIndenter noop if <code>lineIndenter</code> is <code>null</code>
	 */
	@Override
	public void setLineIndenter(LineIndenter lineIndenter)
	{
		this.lineIndenter = notNull(lineIndenter);
	}

	@Override
	public LineIndenter getLineIndenter()
	{
		return notNull(lineIndenter);
	}
	
	/**
	 * @return indented {@link #output}
	 * @see de.jmda.gen.Generator#generate()
	 */
	@Override
	public StringBuffer generate() throws GeneratorException
	{
		return lineIndenter.indent(output);
	}

	/**
	 * @param input
	 * @see #setOutput(StringBuffer)
	 */
	protected void setOutput(String input)
	{
		output = new StringBuffer(input);
	}

	/**
	 * Subclasses need a way to modify {@link #output} other than constructor
	 * injection.
	 *
	 * @param input
	 */
	protected void setOutput(StringBuffer input)
	{
		output = input;
	}

	private LineIndenter notNull(LineIndenter lineIndenter)
  {
		if (lineIndenter == null)
		{
			lineIndenter = new LineIndenter();
		}
		
		return lineIndenter;
  }

	/**
	 * Convenience method to create a <code>Generator</code> that produces <code>
	 * input</code>.
	 *
	 * @param input
	 * @return
	 */
	public static DefaultGenerator dg(String input)
	{
		return new DefaultGenerator(input);
	}
}